home *** CD-ROM | disk | FTP | other *** search
- /*
- * Program: Mailbox Access routines
- *
- * Author: Mark Crispin
- * Networks and Distributed Computing
- * Computing & Communications
- * University of Washington
- * Administration Building, AG-44
- * Seattle, WA 98195
- * Internet: MRC@CAC.Washington.EDU
- *
- * Date: 22 November 1989
- * Last Edited: 6 May 1992
- *
- * Copyright 1992 by the University of Washington
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appears in all copies and that both the
- * above copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington not be
- * used in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. This software is made
- * available "as is", and
- * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
- * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
- * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
- * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-
- #include <ctype.h>
- #include <stdio.h>
- #if unix
- #include <sys/types.h>
- #endif
- #include "osdep.h"
- #include "mail.h"
- #include "misc.h"
-
- DRIVER *maildrivers = NIL; /* list of mail drivers */
- mailgets_t mailgets = NIL; /* pointer to alternate gets function */
-
- /* Default limited get string
- * Accepts: readin function pointer
- * stream to use
- * number of bytes
- * Returns: string read in, truncated if necessary
- *
- * This is a sample mailgets routine. It simply truncates any data larger
- * than MAXMESSAGESIZE. On most systems, you generally don't use a mailgets
- * routine at all, but on some systems (e.g. DOS) it's required to prevent the
- * application from crashing. This one is filled in by the os driver for any
- * OS that requires a mailgets routine and the main program has not already
- * supplied one, generally in tcp_open().
- */
-
- char *mm_gets (f,stream,size)
- readfn_t f;
- void *stream;
- unsigned long size;
- {
- char *s;
- char tmp[MAILTMPLEN+1];
- unsigned long i,j = 0;
- /* truncate? */
- if (i = (size > MAXMESSAGESIZE)) {
- sprintf (tmp,"%ld character literal truncated to %ld characters",
- size,MAXMESSAGESIZE);
- mm_log (tmp,WARN); /* warn user */
- i = size - MAXMESSAGESIZE; /* number of bytes of slop */
- size = MAXMESSAGESIZE; /* maximum length string we can read */
- }
- s = (char *) fs_get (size + 1);
- *s = '\0'; /* init in case getbuffer fails */
- (*f) (stream,size,s); /* get the literal */
- /* toss out everything after that */
- while (i -= j) (*f) (stream,j = min ((long) MAILTMPLEN,i),tmp);
- return s;
- }
-
- /* Mail routines
- *
- * mail_xxx routines are the interface between this module and the outside
- * world. Only these routines should be referenced by external callers.
- *
- * Note that there is an important difference between a "sequence" and a
- * "message #" (msgno). A sequence is a string representing a sequence in
- * {"n", "n:m", or combination separated by commas} format, whereas a msgno
- * is a single integer.
- *
- */
-
- /* Mail link driver
- * Accepts: driver to add to list
- */
-
- void mail_link (driver)
- DRIVER *driver;
- {
- DRIVER **d = &maildrivers;
- while (*d) d = &(*d)->next; /* find end of list of drivers */
- *d = driver; /* put driver at the end */
- driver->next = NIL; /* this driver is the end of the list */
- }
-
-
- /* Mail find list of mailboxes
- * Accepts: mail stream
- * pattern to search
- */
-
- void mail_find (stream,pat)
- MAILSTREAM *stream;
- char *pat;
- {
- DRIVER **d = &maildrivers;
- /* if have a stream, do it for that stream */
- if (stream && stream->dtb) (*stream->dtb->find) (stream,pat);
- /* otherwise do for all DTB's */
- else do ((*d)->find) (NIL,pat);
- while (*(d = &(*d)->next)); /* until at the end */
- }
-
-
- /* Mail find list of bboards
- * Accepts: mail stream
- * pattern to search
- */
-
- void mail_find_bboards (stream,pat)
- MAILSTREAM *stream;
- char *pat;
- {
- DRIVER **d = &maildrivers;
- if (stream && stream->dtb) (*stream->dtb->find_bboard) (stream,pat);
- else do ((*d)->find_bboard) (NIL,pat);
- while (*(d = &(*d)->next)); /* until at the end */
- }
-
- /* Mail open
- * Accepts: candidate stream for recycling
- * mailbox name
- * initial debugging flag
- * Returns: stream to use on success, NIL on failure
- */
-
- MAILSTREAM *mail_open (stream,name,debug)
- MAILSTREAM *stream;
- char *name;
- long debug;
- {
- long i;
- char tmp[MAILTMPLEN];
- DRIVER *factory = maildrivers ? (*maildrivers->valid) (name) : NIL;
- if (factory) { /* must have a factory */
- if (!stream) { /* instantiate stream if none to recycle */
- stream = (MAILSTREAM *) fs_get (sizeof (MAILSTREAM));
- stream->dtb = factory; /* initialize stream fields */
- stream->local = NIL;
- stream->mailbox = cpystr (name);
- stream->lock = stream->debug = stream->silent = stream->readonly =
- stream->anonymous = NIL;
- stream->use = stream->sequence = stream->gensym = stream->nmsgs =
- stream->recent = 0;
- stream->flagstring = NIL;
- for (i = 0; i < NUSERFLAGS; ++i) stream->user_flags[i] = NIL;
- stream->cache = NIL; /* no cache */
- stream->cachesize = 0;
- }
- else { /* close driver if different from factory */
- if (stream->dtb != factory) {
- if (stream->dtb) (*stream->dtb->close) (stream);
- stream->dtb = factory; /* establish factory as our driver */
- stream->local = NIL; /* flush old driver's local data */
- }
- /* clear old silent and readonly state */
- stream->silent = stream->readonly = NIL;
- /* clean up old stream for recycling */
- if (stream->mailbox) fs_give ((void **) &stream->mailbox);
- stream->mailbox = cpystr (name);
- mail_free_cache (&stream->cache,&stream->cachesize);
- }
- if (debug == 36) { /* special hack from Tenex? */
- stream->debug = NIL; /* yes, no special debugging */
- stream->silent = T; /* request silence */
- }
- /* a second grotesque hack */
- else if (debug == 69) stream->anonymous = T;
- else stream->debug = debug; /* set to desired debugging state */
- /* have driver open, flush if failed */
- if (!(*factory->open) (stream)) stream = mail_close (stream);
- }
- else if (debug != 36) { /* not from Tenex internal please */
- sprintf (tmp,"Unknown mailbox format: %.80s",name);
- mm_log (tmp,ERROR); /* give an error */
- }
- return stream; /* return the stream */
- }
-
- /* Mail close
- * Accepts: mail stream
- * Returns: NIL
- */
-
- MAILSTREAM *mail_close (stream)
- MAILSTREAM *stream;
- {
- long i;
- if (stream) { /* make sure argument given */
- /* do the driver's close action */
- if (stream->dtb) (*stream->dtb->close) (stream);
- stream->dtb = NIL; /* disassociate from driver */
- stream->local = NIL; /* and driver's local data */
- if (stream->mailbox) fs_give ((void **) &stream->mailbox);
- stream->mailbox = NIL;
- stream->sequence++; /* invalidate sequence */
- if (stream->flagstring) fs_give ((void **) &stream->flagstring);
- stream->flagstring = NIL;
- for (i = 0; i < NUSERFLAGS; ++i) stream->user_flags[i] = NIL;
- mail_free_cache (&stream->cache,&stream->cachesize);
- /* finally free the stream's storage */
- if (!stream->use) fs_give ((void **) &stream);
- }
- return NIL;
- }
-
- /* Mail make handle
- * Accepts: Mail stream
- * Returns: handle
- *
- * Handles provide a way to have multiple pointers to a stream yet allow the
- * stream's owner to nuke it or recycle it.
- */
-
- MAILHANDLE *mail_makehandle (stream)
- MAILSTREAM *stream;
- {
- MAILHANDLE *handle = (MAILHANDLE *) fs_get (sizeof (MAILHANDLE));
- handle->stream = stream; /* copy stream */
- /* and its sequence */
- handle->sequence = stream->sequence;
- stream->use++; /* let stream know another handle exists */
- return handle;
- }
-
-
- /* Mail release handle
- * Accepts: Mail handle
- */
-
- void mail_free_handle (handle)
- MAILHANDLE **handle;
- {
- MAILSTREAM *s;
- if (*handle) { /* only free if exists */
- /* resign stream, flush unreferenced zombies */
- if ((!--(s = (*handle)->stream)->use) && !s->dtb) fs_give ((void **) &s);
- fs_give ((void **) handle); /* now flush the handle */
- }
- }
-
-
- /* Mail get stream handle
- * Accepts: Mail handle
- * Returns: Mail stream or NIL if stream gone
- */
-
- MAILSTREAM *mail_stream (handle)
- MAILHANDLE *handle;
- {
- MAILSTREAM *s = handle->stream;
- return (s->dtb && (handle->sequence == s->sequence)) ? s : NIL;
- }
-
- /* Mail fetch cache element
- * Accepts: Mail stream
- * message # to fetch
- * Returns: cache element of this message
- * Can also be used to create cache elements for new messages.
- */
-
- MESSAGECACHE *mail_elt (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- long i = msgno - 1;
- if (msgno < 1) fatal ("mail_elt called for non-positive message number");
- mail_cache (stream,msgno); /* make sure cache is large enough */
- if (!stream->cache[i]) { /* if no cache entry, create it */
- stream->cache[i] = (MESSAGECACHE *) fs_get (sizeof (MESSAGECACHE));
- /* initialize newly-created cache entry */
- stream->cache[i]->lockcount = 1;
- stream->cache[i]->msgno = msgno;
- stream->cache[i]->internal_date = NIL;
- stream->cache[i]->seen = stream->cache[i]->deleted =
- stream->cache[i]->flagged = stream->cache[i]->answered =
- stream->cache[i]->searched = stream->cache[i]->recent = NIL;
- stream->cache[i]->user_flags = NIL;
- stream->cache[i]->rfc822_size = 0;
- stream->cache[i]->env = NIL;
- stream->cache[i]->body = NIL;
- }
- return stream->cache[i]; /* return the cache element */
- }
-
-
- /* Mail make cache large enough for given number of messages
- * Accepts: Mail stream
- * number of messages in cache
- */
-
- void mail_cache (stream,size)
- MAILSTREAM *stream;
- long size;
- {
- size_t new;
- unsigned long i = stream->cachesize;
- /* do nothing if size adequate */
- if (size <= stream->cachesize) return;
- new = (stream->cachesize = size + CACHEINCREMENT) * sizeof (MESSAGECACHE *);
- if (stream->cache) fs_resize ((void **) &stream->cache,new);
- else stream->cache = (MESSAGECACHE **) fs_get (new);
- /* init cache */
- while (i < stream->cachesize) stream->cache[i++] = NIL;
- }
-
- /* Mail fetch fast information
- * Accepts: Mail stream
- * sequence
- *
- * Generally, mail_fetchenvelope is preferred
- */
-
- void mail_fetchfast (stream,sequence)
- MAILSTREAM *stream;
- char *sequence;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->fetchfast) (stream,sequence);
- }
-
-
- /* Mail fetch flags
- * Accepts: Mail stream
- * sequence
- */
-
- void mail_fetchflags (stream,sequence)
- MAILSTREAM *stream;
- char *sequence;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->fetchflags) (stream,sequence);
- }
-
-
- /* Mail fetch envelope
- * Accepts: Mail stream
- * message # to fetch
- * Returns: envelope of this message
- *
- * Fetches the "fast" information as well
- */
-
- ENVELOPE *mail_fetchenvelope (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- if (msgno > stream->nmsgs)
- fatal ("mail_fetchenvelope called for non-existent message number");
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->fetchenvelope) (stream,msgno) : NIL;
- }
-
- /* Mail fetch message header
- * Accepts: Mail stream
- * message # to fetch
- * Returns: message header in RFC822 format
- */
-
- char *mail_fetchheader (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- if (msgno > stream->nmsgs)
- fatal ("mail_fetchheader called for non-existent message number");
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->fetchheader) (stream,msgno) : "";
- }
-
-
- /* Mail fetch message text (only)
- body only;
- * Accepts: Mail stream
- * message # to fetch
- * Returns: message text in RFC822 format
- */
-
- char *mail_fetchtext (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- if (msgno > stream->nmsgs)
- fatal ("mail_fetchtext called for non-existent message number");
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->fetchtext) (stream,msgno) : "";
- }
-
-
- /* Mail fetch message body as a structure
- * Accepts: Mail stream
- * message # to fetch
- * section specifier (#.#.#...#)
- * pointer to returned length
- * Returns: pointer to section of message body
- */
-
- char *mail_fetchbody (stream,m,sec,len)
- MAILSTREAM *stream;
- long m;
- char *sec;
- unsigned long *len;
- {
- if (m > stream->nmsgs)
- fatal ("mail_fetchbody called for non-existent message number");
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->fetchbody) (stream,m,sec,len) : "";
- }
-
- /* Mail fetch From string for menu
- * Accepts: destination string
- * Mail stream
- * message # to fetch
- * desired string length
- * Returns: string of requested length
- */
-
- void mail_fetchfrom (s,stream,msgno,length)
- char *s;
- MAILSTREAM *stream;
- long msgno;
- long length;
- {
- char *t;
- char tmp[MAILTMPLEN];
- ENVELOPE *env = mail_fetchenvelope (stream,msgno);
- memset (s,' ',length); /* fill it with spaces */
- s[length] = '\0'; /* tie off with null */
- /* get first from address from envelope */
- if (env && env->from) { /* if a personal name exists use it */
- if (!(t = env->from->personal))
- sprintf (t = tmp,"%s@%s",env->from->mailbox,env->from->host);
- memcpy (s,t,min (length,(long) strlen (t)));
- }
- }
-
-
- /* Mail fetch Subject string for menu
- * Accepts: destination string
- * Mail stream
- * message # to fetch
- * desired string length
- * Returns: string of no more than requested length
- */
-
- void mail_fetchsubject (s,stream,msgno,length)
- char *s;
- MAILSTREAM *stream;
- long msgno;
- long length;
- {
- ENVELOPE *env = mail_fetchenvelope (stream,msgno);
- memset (s,'\0',length+1);
- /* copy subject from envelope */
- if (env && env->subject) strncpy (s,env->subject,length);
- else *s = ' '; /* if no subject then just a space */
- }
-
- /* Mail set flag
- * Accepts: Mail stream
- * sequence
- * flag(s)
- */
-
- void mail_setflag (stream,sequence,flag)
- MAILSTREAM *stream;
- char *sequence;
- char *flag;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->setflag) (stream,sequence,flag);
- }
-
-
- /* Mail clear flag
- * Accepts: Mail stream
- * sequence
- * flag(s)
- */
-
- void mail_clearflag (stream,sequence,flag)
- MAILSTREAM *stream;
- char *sequence;
- char *flag;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->clearflag) (stream,sequence,flag);
- }
-
-
- /* Mail search for messages
- * Accepts: Mail stream
- * search criteria
- */
-
- void mail_search (stream,criteria)
- MAILSTREAM *stream;
- char *criteria;
- {
- long i = 1;
- while (i <= stream->nmsgs) mail_elt (stream,i++)->searched = NIL;
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->search) (stream,criteria);
- }
-
-
- /* Mail ping mailbox
- * Accepts: Mail stream
- * Returns: stream if still open else NIL
- */
-
- long mail_ping (stream)
- MAILSTREAM *stream;
- {
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->ping) (stream) : NIL;
- }
-
- /* Mail check mailbox
- * Accepts: Mail stream
- */
-
- void mail_check (stream)
- MAILSTREAM *stream;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->check) (stream);
- }
-
-
- /* Mail expunge mailbox
- * Accepts: Mail stream
- */
-
- void mail_expunge (stream)
- MAILSTREAM *stream;
- {
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->expunge) (stream);
- }
-
-
- /* Mail copy message(s)
- s;
- * Accepts: Mail stream
- * sequence
- * destination mailbox
- */
-
- long mail_copy (stream,sequence,mailbox)
- MAILSTREAM *stream;
- char *sequence;
- char *mailbox;
- {
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->copy) (stream,sequence,mailbox) : NIL;
- }
-
-
- /* Mail move message(s)
- s;
- * Accepts: Mail stream
- * sequence
- * destination mailbox
- */
-
- long mail_move (stream,sequence,mailbox)
- MAILSTREAM *stream;
- char *sequence;
- char *mailbox;
- {
- /* do the driver's action */
- return stream->dtb ? (*stream->dtb->move) (stream,sequence,mailbox) : NIL;
- }
-
- /* Mail garbage collect stream
- * Accepts: Mail stream
- * garbage collection flags
- */
-
- void mail_gc (stream,gcflags)
- MAILSTREAM *stream;
- long gcflags;
- {
- unsigned long i = 0;
- MESSAGECACHE *elt;
- if (gcflags & GC_ENV) /* garbage collect envelopes? */
- while (i < stream->nmsgs)
- if ((elt = stream->cache[i++]) && elt->env) {
- mail_free_envelope (&elt->env);
- mail_free_body (&elt->body);
- }
- /* do the driver's action */
- if (stream->dtb) (*stream->dtb->gc) (stream,gcflags);
- }
-
- /* Mail messages have been searched out
- * Accepts: MAIL stream
- * message number
- *
- * Calls external "mm_searched" function to notify main program
- */
-
- void mail_searched (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- /* mark as searched */
- mail_elt (stream,msgno)->searched = T;
- mm_searched (stream,msgno); /* notify main program */
- }
-
-
- /* Mail n messages exist
- * Accepts: MAIL stream
- * number of messages
- *
- * Calls external "mm_exists" function that notifies main program prior
- * to updating the stream
- */
-
- void mail_exists (stream,nmsgs)
- MAILSTREAM *stream;
- long nmsgs;
- {
- mail_cache (stream,nmsgs); /* make sure cache is large enough */
- /* notify main program of change */
- if (!stream->silent) mm_exists (stream,nmsgs);
- stream->nmsgs = nmsgs; /* update stream status */
- }
-
- /* Mail n messages are recent
- * Accepts: MAIL stream
- * number of recent messages
- */
-
- void mail_recent (stream,recent)
- MAILSTREAM *stream;
- long recent;
- {
- stream->recent = recent; /* update stream status */
- }
-
-
- /* Mail message n is expunged
- * Accepts: MAIL stream
- * message #
- *
- * Calls external "mm_expunged" function that notifies main program prior
- * to updating the stream
- */
-
- void mail_expunged (stream,msgno)
- MAILSTREAM *stream;
- long msgno;
- {
- long i = msgno - 1;
- if (stream->cache[i]) { /* if an element is there */
- stream->cache[i]->msgno = 0;/* invalidate its message number */
- /* maybe free this message element */
- mail_free_elt (&stream->cache[i]);
- }
- /* slide down remainder of cache */
- for (i = msgno; i < stream->nmsgs; ++i)
- if (stream->cache[i-1] = stream->cache[i]) stream->cache[i-1]->msgno = i;
- stream->cache[stream->nmsgs-1] = NIL;
- --stream->nmsgs; /* update stream status */
- /* notify main program of change */
- if (!stream->silent) mm_expunged (stream,msgno);
- }
-
- /* Mail stream status routines */
-
-
- /* Mail lock stream
- * Accepts: Mail stream
- */
-
- void mail_lock (stream)
- MAILSTREAM *stream;
- {
- if (stream->lock) fatal ("Lock when already locked");
- else stream->lock = T; /* lock stream */
- }
-
-
- /* Mail unlock stream
- * Accepts: Mail stream
- */
-
- void mail_unlock (stream)
- MAILSTREAM *stream;
- {
- if (!stream->lock) fatal ("Unlock when not locked");
- else stream->lock = NIL; /* unlock stream */
- }
-
-
- /* Mail turn on debugging telemetry
- * Accepts: Mail stream
- */
-
- void mail_debug (stream)
- MAILSTREAM *stream;
- {
- stream->debug = T; /* turn on debugging telemetry */
- }
-
-
- /* Mail turn off debugging telemetry
- * Accepts: Mail stream
- */
-
- void mail_nodebug (stream)
- MAILSTREAM *stream;
- {
- stream->debug = NIL; /* turn off debugging telemetry */
- }
-
- /* Mail parse sequence
- * Accepts: MAIL stream
- * sequence to parse
- * Returns: T if parse successful, else NIL
- */
-
- long mail_sequence (stream,sequence)
- MAILSTREAM *stream;
- char *sequence;
- {
- long i,j,x;
- for (i = 1; i <= stream->nmsgs; i++) mail_elt (stream,i)->sequence = NIL;
- while (*sequence) { /* while there is something to parse */
- /* parse and validate message number */
- if (((i = (int) strtol ((const char *) sequence,&sequence,10)) < 1) ||
- (i > stream->nmsgs)) {
- mm_log ("Sequence invalid",ERROR);
- return NIL;
- }
- switch (*sequence) { /* see what the delimiter is */
- case ':': /* sequence range */
- /* parse end of range */
- if (((j = (int) strtol ((const char *) ++sequence,&sequence,10)) < 1) ||
- (j > stream->nmsgs) || (*sequence && *sequence++ != ',')) {
- mm_log ("Sequence range invalid",ERROR);
- return NIL;
- }
- if (i > j) { /* swap the range if backwards */
- x = i; i = j; j = x;
- }
- /* mark each item in the sequence */
- while (i <= j) mail_elt (stream,j--)->sequence = T;
- break;
- case ',': /* single message */
- ++sequence; /* skip the delimiter, fall into end case */
- case '\0': /* end of sequence, mark this message */
- mail_elt (stream,i)->sequence = T;
- break;
- default: /* anything else is a syntax error! */
- mm_log ("Syntax error in sequence",ERROR);
- return NIL;
- }
- }
- return T; /* successfully parsed sequence */
- }
-
- /* Mail data structure instantiation routines */
-
-
- /* Mail instantiate envelope
- * Returns: new envelope
- */
-
- ENVELOPE *mail_newenvelope ()
- {
- ENVELOPE *env = (ENVELOPE *) fs_get (sizeof (ENVELOPE));
- env->remail = NIL; /* initialize all fields */
- env->return_path = NIL;
- env->date = NIL;
- env->subject = NIL;
- env->from = env->sender = env->reply_to = env->to = env->cc = env->bcc = NIL;
- env->in_reply_to = env->message_id = env->newsgroups = NIL;
- return env;
- }
-
-
- /* Mail instantiate address
- * Returns: new address
- */
-
- ADDRESS *mail_newaddr ()
- {
- ADDRESS *adr = (ADDRESS *) fs_get (sizeof (ADDRESS));
- /* initialize all fields */
- adr->personal = adr->adl = adr->mailbox = adr->host = adr->error = NIL;
- adr->next = NIL;
- return adr;
- }
-
-
- /* Mail instantiate body
- * Returns: new body
- */
-
- BODY *mail_newbody ()
- {
- return mail_initbody ((BODY *) fs_get (sizeof (BODY)));
- }
-
- /* Mail initialize body
- * Accepts: body
- * Returns: body
- */
-
- BODY *mail_initbody (body)
- BODY *body;
- {
- body->type = TYPETEXT; /* content type */
- body->encoding = ENC7BIT; /* content encoding */
- body->subtype = body->id = body->description = NIL;
- body->parameter = NIL;
- body->contents.text = NIL; /* no contents yet */
- body->contents.binary = NIL;
- body->contents.part = NIL;
- body->contents.msg.env = NIL;
- body->contents.msg.body = NIL;
- body->contents.msg.text = NIL;
- body->size.lines = body->size.bytes = body->size.ibytes = 0;
- return body;
- }
-
-
- /* Mail instantiate body parameter
- * Returns: new body part
- */
-
- PARAMETER *mail_newbody_parameter ()
- {
- PARAMETER *parameter = (PARAMETER *) fs_get (sizeof (PARAMETER));
- parameter->attribute = parameter->value = NIL;
- parameter->next = NIL; /* no next yet */
- return parameter;
- }
-
-
- /* Mail instantiate body part
- * Returns: new body part
- */
-
- PART *mail_newbody_part ()
- {
- PART *part = (PART *) fs_get (sizeof (PART));
- mail_initbody (&part->body); /* initialize the body */
- part->offset = 0; /* no offset yet */
- part->next = NIL; /* no next yet */
- return part;
- }
-
- /* Mail garbage collection routines */
-
-
- /* Mail garbage collect body
- * Accepts: pointer to body pointer
- */
-
- void mail_free_body (body)
- BODY **body;
- {
- if (*body) { /* only free if exists */
- mail_free_body_data (*body);/* free its data */
- fs_give ((void **) body); /* return body to free storage */
- }
- }
-
-
- /* Mail garbage collect body data
- * Accepts: body pointer
- */
-
- void mail_free_body_data (body)
- BODY *body;
- {
- if (body->subtype) fs_give ((void **) &body->subtype);
- mail_free_body_parameter (&body->parameter);
- if (body->id) fs_give ((void **) &body->id);
- if (body->description) fs_give ((void **) &body->description);
- switch (body->type) { /* free contents */
- case TYPETEXT: /* unformatted text */
- if (body->contents.text) fs_give ((void **) &body->contents.text);
- break;
- case TYPEMULTIPART: /* multiple part */
- mail_free_body_part (&body->contents.part);
- break;
- case TYPEMESSAGE: /* encapsulated message */
- mail_free_envelope (&body->contents.msg.env);
- mail_free_body (&body->contents.msg.body);
- if (body->contents.msg.text)
- fs_give ((void **) &body->contents.msg.text);
- break;
- case TYPEAPPLICATION: /* application data */
- case TYPEAUDIO: /* audio */
- case TYPEIMAGE: /* static image */
- case TYPEVIDEO: /* video */
- if (body->contents.binary) fs_give (&body->contents.binary);
- break;
- default:
- break;
- }
- }
-
- /* Mail garbage collect body parameter
- * Accepts: pointer to body parameter pointer
- */
-
- void mail_free_body_parameter (parameter)
- PARAMETER **parameter;
- {
- if (*parameter) { /* only free if exists */
- if ((*parameter)->attribute) fs_give ((void **) &(*parameter)->attribute);
- if ((*parameter)->value) fs_give ((void **) &(*parameter)->value);
- /* run down the list as necessary */
- mail_free_body_parameter (&(*parameter)->next);
- /* return body part to free storage */
- fs_give ((void **) parameter);
- }
- }
-
-
- /* Mail garbage collect body part
- * Accepts: pointer to body part pointer
- */
-
- void mail_free_body_part (part)
- PART **part;
- {
- if (*part) { /* only free if exists */
- mail_free_body_data (&(*part)->body);
- /* run down the list as necessary */
- mail_free_body_part (&(*part)->next);
- fs_give ((void **) part); /* return body part to free storage */
- }
- }
-
- /* Mail garbage collect message cache
- * Accepts: pointer to message cache pointer
- *
- * The message cache is set to NIL when this function finishes.
- */
-
- void mail_free_cache (cache,size)
- MESSAGECACHE ***cache;
- unsigned long *size;
- {
- unsigned long i;
- /* free each array element */
- for (i = 0; i < *size; ++i) mail_free_elt (&(*cache)[i]);
- fs_give ((void **) cache); /* return cache to free storage */
- *size = 0; /* note that cache is empty */
- }
-
-
- /* Mail garbage collect cache element
- * Accepts: pointer to cache element pointer
- */
-
- void mail_free_elt (elt)
- MESSAGECACHE **elt;
- {
- /* only free if exists and no sharers */
- if (*elt && !--(*elt)->lockcount) {
- if ((*elt)->internal_date) fs_give ((void **) &(*elt)->internal_date);
- mail_free_envelope (&(*elt)->env);
- mail_free_body (&(*elt)->body);
- fs_give ((void **) elt); /* return cache element to free storage */
- }
- else *elt = NIL; /* else simply drop pointer */
- }
-
- /* Mail garbage collect envelope
- * Accepts: pointer to envelope pointer
- */
-
- void mail_free_envelope (env)
- ENVELOPE **env;
- {
- if (*env) { /* only free if exists */
- if ((*env)->remail) fs_give ((void **) &(*env)->remail);
- mail_free_address (&(*env)->return_path);
- if ((*env)->date) fs_give ((void **) &(*env)->date);
- mail_free_address (&(*env)->from);
- mail_free_address (&(*env)->sender);
- mail_free_address (&(*env)->reply_to);
- if ((*env)->subject) fs_give ((void **) &(*env)->subject);
- mail_free_address (&(*env)->to);
- mail_free_address (&(*env)->cc);
- mail_free_address (&(*env)->bcc);
- if ((*env)->in_reply_to) fs_give ((void **) &(*env)->in_reply_to);
- if ((*env)->message_id) fs_give ((void **) &(*env)->message_id);
- if ((*env)->newsgroups) fs_give ((void **) &(*env)->newsgroups);
- fs_give ((void **) env); /* return envelope to free storage */
- }
- }
-
-
- /* Mail garbage collect address
- * Accepts: pointer to address pointer
- */
-
- void mail_free_address (address)
- ADDRESS **address;
- {
- if (*address) { /* only free if exists */
- if ((*address)->personal) fs_give ((void **) &(*address)->personal);
- if ((*address)->adl) fs_give ((void **) &(*address)->adl);
- if ((*address)->mailbox) fs_give ((void **) &(*address)->mailbox);
- if ((*address)->host) fs_give ((void **) &(*address)->host);
- if ((*address)->error) fs_give ((void **) &(*address)->error);
- mail_free_address (&(*address)->next);
- fs_give ((void **) address);/* return address to free storage */
- }
- }
-